/*
 * NodoArbol.cpp
 *
 *  Created on: 21/04/2011
 *      Author: Casa
 */

#include "NodoArbol.h"
#include "estructuras/lista/Lista.h"
#include "estructuras/storePalabras/contador/Contador.h"
#include "managers/autores/AutoresManager.h"

using namespace std;
/*************************************************************
 * 															 *
 * 						PRIVATE								 *
 * 															 *
 *************************************************************/

/**
 * devuelve el primer caracter de un string
 * @param valor
 */
char NodoArbol::getClave(string const & palabra) {
	return palabra.at(0);
}

/**
 * devuelve el primer caracter de un string
 * @param valor
 */
string NodoArbol::getAsSubValor(string const & palabra) {
	string subValor = "";
	if (palabra.length() > 1) {
		subValor = palabra.substr(1, palabra.length() - 1);
	}
	return subValor;
}

/*************************************************************
 * 															 *
 * 						PUBLIC								 *
 * 															 *
 *************************************************************/

/**
 * Constructor con un valor a contener
 * @param valor el valor a contener
 */
NodoArbol::NodoArbol(string & valor) {
	FB = 0;
	der = NULL;
	hijos = NULL;
	izq = NULL;
	string subValor = "";
	clave = getClave(valor);
	ocurrenciasPalabra = 0;
	esValor = false;

	if (valor.length() > 1) {
		//creo un nuevo arbol con el resto
		hijos = new StorePalabras("hijos");
		subValor = getAsSubValor(valor);
		hijos->insert(subValor);
	} else {
		esValor = true;
		ocurrenciasPalabra++;
	}
}
/**
 * Destructor
 */
NodoArbol::~NodoArbol() {
	delete hijos;
}
/**
 *	Inserta un valor en el NodoArbol
 * @param palabra el valor a insertar
 */
void NodoArbol::insertar(string & valor) {
	string subValor;
	if (valor.length() == 1 && esTuyo(valor)) {

		ocurrenciasPalabra++;
	} else if (esTuyo(valor)) {
		if (hijos == NULL) {
			hijos = new StorePalabras("sub");
		}
		subValor = getAsSubValor(valor);
		hijos->insert(subValor);
	}

}

/**
 * Si el valor pertenece al nodo
 * @param palabra
 * @return
 */
bool NodoArbol::esTuyo(string const &palabra) {
	return getClave(palabra) == clave;
}

/**
 * Obtiene los valores que se almacenan en este nodo ordenados alfabeticamente
 * @return una lista de string con los valores
 */
Lista<string> NodoArbol::getValoresOrdenados() {
	Lista<string> resultado;

	Lista<string> valoresHijos;

	if (this->esValor) {
		string palabra;
		palabra.push_back(this->clave);
		resultado.add(palabra);
	}
	if (this->hijos) {
		valoresHijos.clear();
		valoresHijos.copiarLista(this->hijos->inorden());
		IteradorLista<string> iterador = valoresHijos.iterador();
		string palabraAux;
		while (iterador.tieneSiguiente()) {
			palabraAux = "";
			palabraAux.push_back(this->clave);
			palabraAux = palabraAux + iterador.siguiente();
			resultado.add(palabraAux);
		}
	}

	return resultado;
}
/**
 * * Obtiene los valores que se almacenan en este nodo ordenados alfabeticamente
 * @param autor el autor pedido  (si el autor esta vacio se asume que son los dos)
 * @return una lista de contadores con las ocurrencias pedidas
 */
Lista<Contador> NodoArbol::getValoresOrdenadosContador() {
	Lista<Contador> resultado;
	Contador palabraAux;
	Lista<Contador> valoresHijos;
	Contador palabra;
	string aux;
	if (this->esValor) {
		aux = this->clave;
		palabra.setPalabra(aux);
		palabra.setOcurrencias(this->ocurrenciasPalabra);
		resultado.add(palabra);
	}

	if (this->hijos) {
		valoresHijos.clear();
		valoresHijos.copiarLista(this->hijos->inordenSinComparador());
		IteradorLista<Contador> iterador = valoresHijos.iterador();
		while (iterador.tieneSiguiente()) {
			palabraAux = iterador.siguiente();

			resultado.add(palabraAux.agregarRaiz(this->clave));
		}
	}

	return resultado;
}

/**
 * getter del nodo izquier
 * @return el nodo izquierdo
 */
NodoArbol *NodoArbol::getIzq() {
	return izq;
}

/**
 * getter del nodo derecho
 * @return el nodo derecho
 */
NodoArbol *NodoArbol::getDer() {
	return der;
}

/**
 * Getter de valor
 * @return la clave que lo caracteriza
 */
char NodoArbol::getKey() {
	return clave;
}

/**
 * Obtener ocurrenciasTotales de un autor, si el autor pedido es nulo devuelve todas las ocurrenciasTotales de la palabra
 * @param valor el valor a consultar
 * @return
 */
int NodoArbol::getOcurrencias(string & valor) {
	int total = 0;
	if (esTuyo(valor)) {
		if (valor.length() == 1) {
			total = this->ocurrenciasPalabra;
		} else {
			if(hijos){
				total = hijos->getOcurrencias(getAsSubValor(valor));
			} else
				total = 0;

		}
	}
	return total;
}

/**
 * Setter del nodo izquierdo
 * @param nodo
 */
void NodoArbol::setIzq(NodoArbol *nodo) {
	izq = nodo;
}
/**
 * Setter del nodo Derecho
 * @param nodo
 */
void NodoArbol::setDer(NodoArbol *nodo) {
	der = nodo;
}
/**
 * Setter del factor balance
 * @param factorBalance factor balance a setear
 */

void NodoArbol::addOcurrencias(string & palabra, int ocurrencias) {

	if (esTuyo(palabra)) {
		if (palabra.length() == 1) {
			this->ocurrenciasPalabra += ocurrencias;
		} else {
			string subvalor =getAsSubValor(palabra);
			hijos->agregarOcurrencias(subvalor,ocurrencias);
		}
	}
}

void NodoArbol::setFactorBalance(int factorBalance) {
	FB = factorBalance;

}
/**
 * Getter del factor balance
 * @return el factor balance
 */

int NodoArbol::getFactorBalance() {
	return FB;

}

